//
// web_client.hpp
//
// Library: SocialBox
// Package: 
// Module:  web_client
//
// Definition of the WebClient class.
//
// Copyright (c) 2007, Bertrand Cachet and Contributors.
//
//

#ifndef SOCIALBOX_WEB_CLIENT_HPP
#define SOCIALBOX_WEB_CLIENT_HPP

/*!
  \file web_client.hpp
*/

/****************************************************
*       Forward declaration
****************************************************/
//template <class Key, class T>
//class HashMap;

/****************************************************
*       STD dependencies
****************************************************/
#include <string>
#include <list>
#include <iosfwd> // Forward declaration of istd::ostream

/****************************************************
*       POCO C++ dependencies
****************************************************/
#include <Poco/HashMap.h>
#include <Poco/Net/HTTPCookie.h>

/****************************************************
*       SocialBox dependencies
****************************************************/
#include "macros.h"
/****************************************************
*       WebClient class declatation
****************************************************/

/*!
  \class WebClient
  \brief Class used to access web pages.

  Class that provides a direct interface to HTTP services.
*/
class WebClient
{
public:
    enum SynchronizationMode {
        Asynchronous,
        Synchronous
    };
private:
    enum Operation {
        GetOperation,
        PostOperation
    };
    struct Request
    {
        std::string url;
        int status;
        std::ostream *buffer;
    };
public:
    /*!
    * \brief Constructor
    *
    * \param mode Specify if WebClient is used Synchronously/Asynchronously
    */
    explicit WebClient(const SynchronizationMode mode=Asynchronous);

    /*!
    * \brief Destructor
    */
    virtual ~WebClient();

    /*!
    * \brief HTTP GET method on an URL
    *
    * Function used to perform a HTTP GET method on a given URL
    *
    * \param  url URL to perform the GET method on
    * \param  to Where to store fetched data. If NULL then fetched data
    * is returned by the method
    * \return in Synchonous mode return the status of the request. In asynchronous
    *         mode return the request Id
    */
    int get(const std::string url, std::ostream* to);

    /*!
    * \brief HTTP POST method on an URL
    *
    * Function used to perform a HTTP GET method on a given URL
    *
    * \param  url URL to perform the GET method on
    * \param  args Params that are associated to the HTTP POST method
    * \param  to Where to store fetched data. Can be a file or a memory stream
    * \return in Synchonous mode return the status of the request. In asynchronous
    *         mode return the request Id
    */
    int post(const std::string url, const Poco::HashMap<std::string, std::string> args, std::ostream* to);

    int post(const std::string url, const std::list<std::string> args, std::ostream* to);
    
    int getSynchronizationMode();
    
    void addCookies(const Poco::HashMap<std::string, std::string> cookies);
    
    Poco::HashMap<std::string, std::string> getCookies();
private:
    struct Authentication {
        bool needed;
        std::string username;
        std::string password;
    };
    std::string _host;
    std::string _scheme;
    Authentication _authentication;
    SynchronizationMode _synchronizationMode;
    Poco::HashMap<std::string, std::string> _cookies;

    Poco::HashMap<std::string, Request> *_connections;

    int _makeRequest(const Operation operation, const std::string _url, const std::string args, std::ostream* to);

    void _registerRequest(const std::string url, std::ostream *buffer);

    void _init(const SynchronizationMode mode);
    
private:
    DISALLOW_COPY_AND_ASSIGN(WebClient);
};

#endif // SOCIALBOX_WEB_CLIENT_HPP
